home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / wwbbs31s.lha / Hydra / amiga.c < prev    next >
C/C++ Source or Header  |  1994-06-28  |  28KB  |  1,180 lines

  1. /*
  2. **    Amiga support module for HYDRA protocol sample implementation.
  3. **
  4. **    Written by    Olaf Barthel
  5. **            Brabeckstrasse 35
  6. **            D-30559 Hannover
  7. **
  8. **            eMail: olsen@sourcery.han.de
  9. **
  10. **    Freely distributable.
  11. */
  12.  
  13.     /* System includes. */
  14.  
  15. #include <utility/date.h>
  16.  
  17. #include <devices/serial.h>
  18. #include <devices/timer.h>
  19.  
  20. #include <hardware/cia.h>
  21.  
  22. #include <dos/dosextens.h>
  23. #include <dos/filehandler.h>
  24. #include <dos/dosasl.h>
  25.  
  26. #include <exec/memory.h>
  27.  
  28.     /* Correct a nasty bug in the prototypes. */
  29.  
  30. #define CheckIO foo21234
  31.  
  32. #include <clib/utility_protos.h>
  33. #include <clib/timer_protos.h>
  34. #include <clib/exec_protos.h>
  35. #include <clib/dos_protos.h>
  36. #include <clib/macros.h>
  37.  
  38.     /* Get the CheckIO prototype right. */
  39.  
  40. #undef CheckIO
  41.  
  42. struct IORequest *CheckIO(struct IORequest *);
  43.  
  44. #include "hydracom.h"
  45.  
  46.     /* Serial buffer size. */
  47.  
  48. #define BUFFER_SIZE 8192
  49.  
  50.     /* A handy macro. */
  51.  
  52. #define ClrSignal(s)    SetSignal(0,s)
  53.  
  54.     /* Signal masks. */
  55.  
  56. #define SIG_SERREAD    (1UL << ReadPort -> mp_SigBit)
  57. #define SIG_SERWRITE    (1UL << WritePort -> mp_SigBit)
  58. #define SIG_TIMER    (1UL << TimePort -> mp_SigBit)
  59. #define SIG_WINDOW    (1UL << LocalWindow -> UserPort -> mp_SigBit)
  60.  
  61.     /* A serial buffer structure. */
  62.  
  63. struct SerialBuffer
  64. {
  65.     struct IOExtSer    *SerialRequest;
  66.     UBYTE        *SerialBuffer,
  67.             *SerialIndex,
  68.             *SerialTop;
  69.     LONG         SerialSize,
  70.              SerialFilled;
  71.     BOOL         IsClone,
  72.              IsBusy;
  73. };
  74.  
  75.     /* Library bases. */
  76.  
  77. struct Library
  78.             *UtilityBase,
  79.             *TimerBase;
  80.  
  81.     /* Timer data. */
  82.  
  83. struct MsgPort        *TimePort;
  84. struct timerequest    *TimeRequest;
  85.  
  86.     /* Serial data. */
  87.  
  88. struct MsgPort        *ReadPort,
  89.             *WritePort;
  90.  
  91. struct SerialBuffer    *ThisBuffer,
  92.             *NextBuffer,
  93.             *ReadBuffer;
  94.  
  95.     /* DOS Data. */
  96.  
  97. struct AnchorPath    *Anchor;
  98. BOOL             AnchorUsed = FALSE;
  99.  
  100.     /* CloneSerialBuffer():
  101.      *
  102.      *    Clone a SerialBuffer structure.
  103.      */
  104.  
  105. STATIC struct SerialBuffer * __regargs
  106. CloneSerialBuffer(struct SerialBuffer *Source,struct MsgPort *MsgPort)
  107. {
  108.     struct SerialBuffer *Buffer;
  109.  
  110.     if(Buffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + Source -> SerialSize,MEMF_ANY | MEMF_PUBLIC))
  111.     {
  112.         Buffer -> SerialBuffer    = Buffer -> SerialIndex = (UBYTE *)(Buffer + 1);
  113.         Buffer -> SerialFilled    = 0;
  114.         Buffer -> SerialTop    = Buffer -> SerialBuffer + Source -> SerialSize;
  115.         Buffer -> SerialSize    = Source -> SerialSize;
  116.         Buffer -> IsClone    = TRUE;
  117.         Buffer -> IsBusy    = FALSE;
  118.  
  119.         if(Buffer -> SerialRequest = (struct IOExtSer *)AllocVec(sizeof(struct IOExtSer),MEMF_ANY | MEMF_PUBLIC))
  120.         {
  121.             CopyMem(Source -> SerialRequest,Buffer -> SerialRequest,sizeof(struct IOExtSer));
  122.  
  123.             Buffer -> SerialRequest -> IOSer . io_Message . mn_ReplyPort = MsgPort;
  124.  
  125.             return(Buffer);
  126.         }
  127.         else
  128.             cprint("Could not create serial request\n");
  129.  
  130.         FreeVec(Buffer);
  131.     }
  132.     else
  133.         cprint("Could not create serial buffer\n");
  134.  
  135.     return(NULL);
  136. }
  137.  
  138.     /* DeleteSerialBuffer():
  139.      *
  140.      *    Delete a SerialBuffer structure.
  141.      */
  142.  
  143. STATIC VOID __regargs
  144. DeleteSerialBuffer(struct SerialBuffer *Buffer)
  145. {
  146.     if(Buffer)
  147.     {
  148.         if(Buffer -> IsBusy)
  149.         {
  150.             if(!CheckIO(Buffer -> SerialRequest))
  151.                 AbortIO(Buffer -> SerialRequest);
  152.  
  153.             WaitIO(Buffer -> SerialRequest);
  154.         }
  155. /* Clear */
  156.         Buffer -> SerialRequest -> IOSer . io_Command = CMD_CLEAR;
  157.         DoIO(Buffer -> SerialRequest);
  158.  
  159.         if(Buffer -> IsClone)
  160.             FreeVec(Buffer -> SerialRequest);
  161.         else
  162.         {
  163.             CloseDevice(Buffer -> SerialRequest);
  164.  
  165.             DeleteIORequest(Buffer -> SerialRequest);
  166.         }
  167.  
  168.         FreeVec(Buffer);
  169.     }
  170. }
  171.  
  172.     /* CreateSerialBuffer():
  173.      *
  174.      *    Create a serial buffer structure.
  175.      */
  176.  
  177. STATIC struct SerialBuffer * __regargs
  178. CreateSerialBuffer(STRPTR Device,LONG Unit,LONG Size,struct MsgPort *MsgPort)
  179. {
  180.     struct SerialBuffer *Buffer;
  181.  
  182.     if(Buffer = (struct SerialBuffer *)AllocVec(sizeof(struct SerialBuffer) + Size,MEMF_ANY | MEMF_PUBLIC))
  183.     {
  184.         Buffer -> SerialBuffer    = Buffer -> SerialIndex = (UBYTE *)(Buffer + 1);
  185.         Buffer -> SerialFilled    = 0;
  186.         Buffer -> SerialTop    = Buffer -> SerialBuffer + Size;
  187.         Buffer -> SerialSize    = Size;
  188.         Buffer -> IsClone    = FALSE;
  189.         Buffer -> IsBusy    = FALSE;
  190.  
  191.         if(Buffer -> SerialRequest = (struct IOExtSer *)CreateIORequest(MsgPort,sizeof(struct IOExtSer)))
  192.         {
  193.             Buffer -> SerialRequest -> io_SerFlags |= SERF_SHARED;
  194.             if(!OpenDevice(Device,Unit,Buffer -> SerialRequest,NULL))
  195.                 return(Buffer);
  196.             else
  197.             {
  198.                 cprint("Could not open \"%s\", unit %d\n",Device,Unit);
  199.  
  200.                 DeleteIORequest(Buffer -> SerialRequest);
  201.             }
  202.         }
  203.         else
  204.             cprint("Could not create serial request\n");
  205.  
  206.         FreeVec(Buffer);
  207.     }
  208.     else
  209.         cprint("Could not create serial buffer\n");
  210.  
  211.     return(NULL);
  212. }
  213.  
  214.     /* OpenAll():
  215.      *
  216.      *    Allocate all the resources required.
  217.      */
  218.  
  219. STATIC BOOL
  220. OpenAll(STRPTR Device,LONG Unit)
  221. {
  222.     if(!(UtilityBase = OpenLibrary("utility.library",37)))
  223.     {
  224.         cprint("Could not open utility.library v37\n");
  225.  
  226.         return(FALSE);
  227.     }
  228.  
  229.     if(!(TimePort = CreateMsgPort()))
  230.     {
  231.         cprint("Could not create timer port\n");
  232.  
  233.         return(FALSE);
  234.     }
  235.  
  236.     if(!(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(struct timerequest))))
  237.     {
  238.         cprint("Could not create timer request\n");
  239.  
  240.         return(FALSE);
  241.     }
  242.  
  243.     if(OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,NULL))
  244.     {
  245.         cprint("Could not open timer\n");
  246.  
  247.         return(FALSE);
  248.     }
  249.  
  250.     TimerBase = (struct Library *)TimeRequest -> tr_node . io_Device;
  251.  
  252.     if(!(Anchor = (struct AnchorPath *)AllocVec(sizeof(struct AnchorPath) + 512,MEMF_ANY | MEMF_CLEAR)))
  253.     {
  254.         cprint("Could not allocate pattern matching buffe\n");
  255.  
  256.         return(FALSE);
  257.     }
  258.  
  259.     Anchor -> ap_Strlen = 512;
  260.  
  261.     if(!(ReadPort = CreateMsgPort()))
  262.     {
  263.         cprint("Could not create serial read port\n");
  264.  
  265.         return(FALSE);
  266.     }
  267.  
  268.     if(!(WritePort = CreateMsgPort()))
  269.     {
  270.         cprint("Could not create serial write port\n");
  271.  
  272.         return(FALSE);
  273.     }
  274.  
  275.     if(!(ReadBuffer = CreateSerialBuffer(Device,Unit,BUFFER_SIZE,ReadPort)))
  276.         return(FALSE);
  277.  
  278.     if(!(ThisBuffer = CloneSerialBuffer(ReadBuffer,WritePort)))
  279.         return(FALSE);
  280.  
  281.     if(!(NextBuffer = CloneSerialBuffer(ReadBuffer,WritePort)))
  282.         return(FALSE);
  283.  
  284.     return(TRUE);
  285. }
  286.  
  287.     /* CloseAll():
  288.      *
  289.      *    Close all the resources.
  290.      */
  291.  
  292. STATIC VOID
  293. CloseAll(VOID)
  294. {
  295.     if(AnchorUsed)
  296.         MatchEnd(Anchor);
  297.  
  298.     if(Anchor)
  299.         FreeVec(Anchor);
  300.  
  301.     DeleteSerialBuffer(NextBuffer);
  302.     DeleteSerialBuffer(ThisBuffer);
  303.     DeleteSerialBuffer(ReadBuffer);
  304.  
  305.     if(WritePort)
  306.         DeleteMsgPort(WritePort);
  307.  
  308.     if(ReadPort)
  309.         DeleteMsgPort(ReadPort);
  310.  
  311.     if(TimeRequest)
  312.     {
  313.         if(TimeRequest -> tr_node . io_Device)
  314.             CloseDevice(TimeRequest);
  315.  
  316.         DeleteIORequest(TimeRequest);
  317.     }
  318.  
  319.     if(TimePort)
  320.         DeleteMsgPort(TimePort);
  321.  
  322.     if(UtilityBase)
  323.         CloseLibrary(UtilityBase);
  324.  
  325. }
  326.  
  327.     /* dtr_out(byte flag):
  328.      *
  329.      *    If flag == 0 -> drop DTR signal, else set it.
  330.      */
  331.  
  332. VOID
  333. dtr_out(byte flag)
  334. {
  335.     if(!flag)
  336.     {
  337.         if(ThisBuffer -> IsBusy)
  338.         {
  339.             WaitIO(ThisBuffer -> SerialRequest);
  340.     
  341.             ThisBuffer -> IsBusy        = FALSE;
  342.             ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  343.         }
  344.     
  345.         if(ReadBuffer -> IsBusy)
  346.         {
  347.             if(!CheckIO(ReadBuffer -> SerialRequest))
  348.                 AbortIO(ReadBuffer -> SerialRequest);
  349.  
  350.             WaitIO(ReadBuffer -> SerialRequest);
  351.     
  352.             ReadBuffer -> IsBusy        = FALSE;
  353.             ReadBuffer -> SerialFilled    = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  354.             ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  355.     
  356.             ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  357.     
  358.             DoIO(ReadBuffer -> SerialRequest);
  359.     
  360.             if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  361.             {
  362.                 LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
  363.     
  364.                 if(Size > 0)
  365.                 {
  366.                     if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  367.                         Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  368.     
  369.                     ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  370.                     ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
  371.                     ReadBuffer -> SerialRequest -> IOSer . io_Length    = Size;
  372.     
  373.                     DoIO(ReadBuffer -> SerialRequest);
  374.     
  375.                     ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  376.                 }
  377.             }
  378.         }
  379.  
  380.         CloseDevice(ReadBuffer -> SerialRequest);
  381.  
  382.         TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  383.         TimeRequest -> tr_time . tv_secs    = 1;
  384.         TimeRequest -> tr_time . tv_micro    = 0;
  385.  
  386.         DoIO(TimeRequest);
  387.  
  388.         if(OpenDevice(device,port,ReadBuffer -> SerialRequest,NULL))
  389.         {
  390.             CloseAll();
  391.  
  392.             exit(10);
  393.         }
  394.         else
  395.         {
  396.             ReadBuffer -> SerialRequest -> io_Baud        = ThisBuffer -> SerialRequest -> io_Baud;
  397.             ReadBuffer -> SerialRequest -> io_ReadLen    = ThisBuffer -> SerialRequest -> io_ReadLen;
  398.             ReadBuffer -> SerialRequest -> io_WriteLen    = ThisBuffer -> SerialRequest -> io_WriteLen;
  399.             ReadBuffer -> SerialRequest -> io_SerFlags    = ThisBuffer -> SerialRequest -> io_SerFlags;
  400.  
  401.             ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  402.  
  403.             DoIO(ReadBuffer -> SerialRequest);
  404.  
  405.             CopyMem(ReadBuffer -> SerialRequest,ThisBuffer -> SerialRequest,sizeof(struct IOExtSer));
  406.  
  407.             ThisBuffer -> SerialRequest -> IOSer . io_Message . mn_ReplyPort = WritePort;
  408.  
  409.             CopyMem(ReadBuffer -> SerialRequest,NextBuffer -> SerialRequest,sizeof(struct IOExtSer));
  410.  
  411.             NextBuffer -> SerialRequest -> IOSer . io_Message . mn_ReplyPort = WritePort;
  412.         }
  413.     }
  414. }
  415.  
  416.     /* com_flow(byte flags):
  417.      *
  418.      *    The bit mask `flags' determines the style(s) of
  419.      *    handshaking:
  420.      *
  421.      *    if (flags & 9) -> enable xON/xOFF software handshaking,
  422.      *    if (flags & 2) -> enable RTS/CTS hardware handshaking
  423.      */
  424.  
  425. VOID
  426. com_flow(byte flags)
  427. {
  428.     if(ThisBuffer -> IsBusy)
  429.     {
  430.         WaitIO(ThisBuffer -> SerialRequest);
  431.  
  432.         ThisBuffer -> IsBusy        = FALSE;
  433.         ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  434.     }
  435.  
  436.     if(ReadBuffer -> IsBusy)
  437.     {
  438.         if(!CheckIO(ReadBuffer -> SerialRequest))
  439.             AbortIO(ReadBuffer -> SerialRequest);
  440.  
  441.         WaitIO(ReadBuffer -> SerialRequest);
  442.  
  443.         ReadBuffer -> IsBusy        = FALSE;
  444.         ReadBuffer -> SerialFilled    = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  445.         ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  446.  
  447.         ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  448.  
  449.         DoIO(ReadBuffer -> SerialRequest);
  450.  
  451.         if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  452.         {
  453.             LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
  454.  
  455.             if(Size > 0)
  456.             {
  457.                 if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  458.                     Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  459.  
  460.                 ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  461.                 ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
  462.                 ReadBuffer -> SerialRequest -> IOSer . io_Length    = Size;
  463.  
  464.                 DoIO(ReadBuffer -> SerialRequest);
  465.  
  466.                 ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  467.             }
  468.         }
  469.     }
  470.  
  471.     ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  472.  
  473.     DoIO(ReadBuffer -> SerialRequest);
  474.  
  475.     ThisBuffer -> SerialRequest -> io_SerFlags = ReadBuffer -> SerialRequest -> io_SerFlags;
  476.     NextBuffer -> SerialRequest -> io_SerFlags = ReadBuffer -> SerialRequest -> io_SerFlags;
  477. }
  478.  
  479.     /* com_setspeed(word speed):
  480.      *
  481.      *    Set the transfer speed (in bits/second).
  482.      */
  483.  
  484. VOID
  485. com_setspeed(word speed)
  486. {
  487.     if(ThisBuffer -> IsBusy)
  488.     {
  489.         WaitIO(ThisBuffer -> SerialRequest);
  490.  
  491.         ThisBuffer -> IsBusy        = FALSE;
  492.         ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  493.     }
  494.  
  495.     if(ReadBuffer -> IsBusy)
  496.     {
  497.         if(!CheckIO(ReadBuffer -> SerialRequest))
  498.             AbortIO(ReadBuffer -> SerialRequest);
  499.  
  500.         WaitIO(ReadBuffer -> SerialRequest);
  501.  
  502.         ReadBuffer -> IsBusy        = FALSE;
  503.         ReadBuffer -> SerialFilled    = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  504.         ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  505.  
  506.         ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  507.  
  508.         DoIO(ReadBuffer -> SerialRequest);
  509.  
  510.         if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  511.         {
  512.             LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
  513.  
  514.             if(Size > 0)
  515.             {
  516.                 if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  517.                     Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  518.  
  519.                 ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  520.                 ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
  521.                 ReadBuffer -> SerialRequest -> IOSer . io_Length    = Size;
  522.  
  523.                 DoIO(ReadBuffer -> SerialRequest);
  524.  
  525.                 ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  526.             }
  527.         }
  528.     }
  529.  
  530.     ReadBuffer -> SerialRequest -> io_Baud = speed;
  531.  
  532.     ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  533.  
  534.     DoIO(ReadBuffer -> SerialRequest);
  535.  
  536.     ThisBuffer -> SerialRequest -> io_Baud        = ReadBuffer -> SerialRequest -> io_Baud;
  537.     ThisBuffer -> SerialRequest -> io_ReadLen    = ReadBuffer -> SerialRequest -> io_ReadLen;
  538.     ThisBuffer -> SerialRequest -> io_WriteLen    = ReadBuffer -> SerialRequest -> io_WriteLen;
  539.     ThisBuffer -> SerialRequest -> io_SerFlags    = ReadBuffer -> SerialRequest -> io_SerFlags;
  540.  
  541.     NextBuffer -> SerialRequest -> io_Baud        = ReadBuffer -> SerialRequest -> io_Baud;
  542.     NextBuffer -> SerialRequest -> io_ReadLen    = ReadBuffer -> SerialRequest -> io_ReadLen;
  543.     NextBuffer -> SerialRequest -> io_WriteLen    = ReadBuffer -> SerialRequest -> io_WriteLen;
  544.     NextBuffer -> SerialRequest -> io_SerFlags    = ReadBuffer -> SerialRequest -> io_SerFlags;
  545. }
  546.  
  547.     /* com_putblock(byte *s,word len):
  548.      *
  549.      *    Send a data block asynchronously.
  550.      */
  551.  
  552. VOID
  553. com_putblock(byte *s,word len)
  554. {
  555.     struct SerialBuffer *Swap = ThisBuffer;
  556.  
  557.     if(ThisBuffer -> IsBusy)
  558.         WaitIO(ThisBuffer -> SerialRequest);
  559.     else
  560.     {
  561.         if(ThisBuffer -> SerialIndex > ThisBuffer -> SerialBuffer)
  562.         {
  563.             ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  564.             ThisBuffer -> SerialRequest -> IOSer . io_Data        = ThisBuffer -> SerialBuffer;
  565.             ThisBuffer -> SerialRequest -> IOSer . io_Length    = ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer;
  566.  
  567.             DoIO(ThisBuffer -> SerialRequest);
  568.         }
  569.     }
  570.  
  571.     ThisBuffer -> IsBusy        = FALSE;
  572.     ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  573.  
  574.     ThisBuffer = NextBuffer;
  575.     NextBuffer = Swap;
  576.  
  577.     if(ThisBuffer -> SerialIndex > ThisBuffer -> SerialBuffer)
  578.     {
  579.         ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  580.         ThisBuffer -> SerialRequest -> IOSer . io_Data        = ThisBuffer -> SerialBuffer;
  581.         ThisBuffer -> SerialRequest -> IOSer . io_Length    = ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer;
  582.  
  583.         DoIO(ThisBuffer -> SerialRequest);
  584.     }
  585.  
  586.     ThisBuffer -> IsBusy        = FALSE;
  587.     ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  588.  
  589.     while(len > 2 * ThisBuffer -> SerialSize)
  590.     {
  591.         ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  592.         ThisBuffer -> SerialRequest -> IOSer . io_Data        = s;
  593.         ThisBuffer -> SerialRequest -> IOSer . io_Length    = ThisBuffer -> SerialSize;
  594.  
  595.         s    += ThisBuffer -> SerialSize;
  596.         len    -= ThisBuffer -> SerialSize;
  597.  
  598.         DoIO(ThisBuffer -> SerialRequest);
  599.     }
  600.  
  601.     CopyMem(s,ThisBuffer -> SerialBuffer,MIN(len,ThisBuffer -> SerialSize));
  602.  
  603.     ThisBuffer -> IsBusy                    = TRUE;
  604.     ThisBuffer -> SerialIndex                = ThisBuffer -> SerialBuffer + MIN(len,ThisBuffer -> SerialSize);
  605.     ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  606.     ThisBuffer -> SerialRequest -> IOSer . io_Data        = ThisBuffer -> SerialBuffer;
  607.     ThisBuffer -> SerialRequest -> IOSer . io_Length    = MIN(len,ThisBuffer -> SerialSize);
  608.  
  609.     len    -= ThisBuffer -> SerialRequest -> IOSer . io_Length;
  610.     s    += ThisBuffer -> SerialRequest -> IOSer . io_Length;
  611.  
  612.     ClrSignal(SIG_SERWRITE);
  613.     SendIO(ThisBuffer -> SerialRequest);
  614.  
  615.     if(len > 0)
  616.     {
  617.         CopyMem(s,NextBuffer -> SerialBuffer,len);
  618.  
  619.         NextBuffer -> SerialIndex = NextBuffer -> SerialBuffer + len;
  620.     }
  621. }
  622.  
  623.     /* breakfunc():
  624.      *
  625.      *    Cleanup routine for SAS/C.
  626.      */
  627.  
  628. static int
  629. breakfunc(void)
  630. {
  631.     CloseAll();
  632.  
  633.     return(1);
  634. }
  635.  
  636.     /* sys_init(VOID):
  637.      *
  638.      *    Initialize this driver implementation.
  639.      */
  640.  
  641. VOID
  642. sys_init(VOID)
  643. {
  644.     if(!OpenAll(device,port))
  645.     {
  646.         CloseAll();
  647.  
  648.         endprog(2);
  649.     }
  650.  
  651.     onbreak(breakfunc);
  652. }
  653.  
  654.     /* sys_reset(VOID):
  655.      *
  656.      *    Perform cleanup for this driver implementation.
  657.      */
  658.  
  659. VOID
  660. sys_reset(VOID)
  661. {
  662.     CloseAll();
  663. }
  664.  
  665.     /* sys_idle(VOID):
  666.      *
  667.      *    This routine gets called when the system is idle.
  668.      *    That's a nice one. We are supposed to call the
  669.      *    system scheduler, etc.
  670.      */
  671.  
  672. VOID
  673. sys_idle(VOID)
  674. {
  675.     ULONG Signals;
  676.  
  677.     if(ReadBuffer -> SerialFilled <= 0 && !ReadBuffer -> IsBusy)
  678.     {
  679.         ReadBuffer -> IsBusy                    = TRUE;
  680.         ReadBuffer -> SerialIndex                = ReadBuffer -> SerialBuffer;
  681.         ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  682.         ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer;
  683.         ReadBuffer -> SerialRequest -> IOSer . io_Length    = 1;
  684.  
  685.         ClrSignal(SIG_SERREAD);
  686.         SendIO(ReadBuffer -> SerialRequest);
  687.     }
  688.  
  689.     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  690.     TimeRequest -> tr_time . tv_secs    = 1;
  691.     TimeRequest -> tr_time . tv_micro    = 0;
  692.  
  693.     ClrSignal(SIG_TIMER);
  694.     SendIO(TimeRequest);
  695.  
  696.     Signals = Wait(SIG_SERREAD | SIG_SERWRITE | SIG_TIMER);
  697.  
  698.     if(!(Signals & SIG_TIMER))
  699.     {
  700.         if(!CheckIO(TimeRequest))
  701.             AbortIO(TimeRequest);
  702.     }
  703.  
  704.     WaitIO(TimeRequest);
  705.  
  706.     if(Signals & SIG_SERREAD)
  707.     {
  708.         WaitIO(ReadBuffer -> SerialRequest);
  709.  
  710.         ReadBuffer -> IsBusy        = FALSE;
  711.         ReadBuffer -> SerialFilled    = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  712.         ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  713.  
  714.         ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  715.  
  716.         DoIO(ReadBuffer -> SerialRequest);
  717.  
  718.         if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  719.         {
  720.             LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
  721.  
  722.             if(Size > 0)
  723.             {
  724.                 if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  725.                     Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  726.  
  727.                 ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  728.                 ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
  729.                 ReadBuffer -> SerialRequest -> IOSer . io_Length    = Size;
  730.  
  731.                 DoIO(ReadBuffer -> SerialRequest);
  732.  
  733.                 ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  734.             }
  735.         }
  736.     }
  737.  
  738.     if(Signals & SIG_SERWRITE)
  739.     {
  740.         struct SerialBuffer *Swap = ThisBuffer;
  741.  
  742.         WaitIO(ThisBuffer -> SerialRequest);
  743.  
  744.         ThisBuffer -> IsBusy        = FALSE;
  745.         ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  746.  
  747.         ThisBuffer = NextBuffer;
  748.         NextBuffer = Swap;
  749.     }
  750.  
  751. }
  752.  
  753.     /* com_outfull(VOID):
  754.      *
  755.      *    Return number of bytes still to be transferred.
  756.      */
  757.  
  758. int
  759. com_outfull(VOID)
  760. {
  761.     return(ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer + NextBuffer -> SerialIndex - NextBuffer -> SerialBuffer);
  762. }
  763.  
  764.     /* carrier(VOID):
  765.      *
  766.      *    Return current carrier status.
  767.      */
  768.  
  769. int
  770. carrier(VOID)
  771. {
  772.     if(nocarrier)
  773.         return(1);
  774.     else
  775.     {
  776.         if(!ThisBuffer -> IsBusy)
  777.         {
  778.             ThisBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  779.  
  780.             DoIO(ThisBuffer -> SerialRequest);
  781.  
  782.             if(ThisBuffer -> SerialRequest -> io_Status & CIAF_COMCD)
  783.                 return(0);
  784.             else
  785.                 return(1);
  786.         }
  787.         else
  788.         {
  789.             NextBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  790.  
  791.             DoIO(NextBuffer -> SerialRequest);
  792.  
  793.             if(NextBuffer -> SerialRequest -> io_Status & CIAF_COMCD)
  794.                 return(0);
  795.             else
  796.                 return(1);
  797.         }
  798.     }
  799. }
  800.  
  801.     /* com_flush(VOID):
  802.      *
  803.      *    Make sure all pending data gets written.
  804.      */
  805.  
  806. VOID
  807. com_flush(VOID)
  808. {
  809.     if(ThisBuffer -> IsBusy)
  810.     {
  811.         WaitIO(ThisBuffer -> SerialRequest);
  812.  
  813.         ThisBuffer -> IsBusy        = FALSE;
  814.         ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  815.     }
  816.  
  817.     if(NextBuffer -> SerialIndex > NextBuffer -> SerialBuffer)
  818.     {
  819.         NextBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  820.         NextBuffer -> SerialRequest -> IOSer . io_Data        = NextBuffer -> SerialBuffer;
  821.         NextBuffer -> SerialRequest -> IOSer . io_Length    = NextBuffer -> SerialIndex - NextBuffer -> SerialBuffer;
  822.  
  823.         DoIO(NextBuffer -> SerialRequest);
  824.  
  825.         NextBuffer -> SerialIndex = NextBuffer -> SerialBuffer;
  826.     }
  827. }
  828.  
  829.     /* com_putbyte(byte c):
  830.      *
  831.      *    Transmit a single byte, queueing it if necessary.
  832.      */
  833.  
  834. VOID
  835. com_putbyte(byte c)
  836. {
  837.     if(ThisBuffer -> IsBusy)
  838.     {
  839.         if(NextBuffer -> SerialIndex + 1 >= NextBuffer -> SerialTop)
  840.         {
  841.             struct SerialBuffer *Swap = ThisBuffer;
  842.  
  843.             WaitIO(ThisBuffer -> SerialRequest);
  844.  
  845.             ThisBuffer -> IsBusy        = FALSE;
  846.             ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  847.  
  848.             ThisBuffer = NextBuffer;
  849.             NextBuffer = Swap;
  850.  
  851.             ThisBuffer -> IsBusy                    = TRUE;
  852.             ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  853.             ThisBuffer -> SerialRequest -> IOSer . io_Data        = ThisBuffer -> SerialBuffer;
  854.             ThisBuffer -> SerialRequest -> IOSer . io_Length    = ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer;
  855.  
  856.             ClrSignal(SIG_SERWRITE);
  857.             SendIO(ThisBuffer -> SerialRequest);
  858.         }
  859.  
  860.         *NextBuffer -> SerialIndex++ = c;
  861.     }
  862.     else
  863.     {
  864.         if(ThisBuffer -> SerialIndex + 1 < ThisBuffer -> SerialTop)
  865.         {
  866.             *ThisBuffer -> SerialIndex++ = c;
  867.  
  868.             ThisBuffer -> IsBusy                    = TRUE;
  869.             ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  870.             ThisBuffer -> SerialRequest -> IOSer . io_Data        = ThisBuffer -> SerialBuffer;
  871.             ThisBuffer -> SerialRequest -> IOSer . io_Length    = 1;
  872.  
  873.             ClrSignal(SIG_SERWRITE);
  874.             SendIO(ThisBuffer -> SerialRequest);
  875.         }
  876.         else
  877.         {
  878.             ThisBuffer -> IsBusy                    = TRUE;
  879.             ThisBuffer -> SerialRequest -> IOSer . io_Command    = CMD_WRITE;
  880.             ThisBuffer -> SerialRequest -> IOSer . io_Data        = ThisBuffer -> SerialBuffer;
  881.             ThisBuffer -> SerialRequest -> IOSer . io_Length    = ThisBuffer -> SerialIndex - ThisBuffer -> SerialBuffer;
  882.  
  883.             ClrSignal(SIG_SERWRITE);
  884.             SendIO(ThisBuffer -> SerialRequest);
  885.  
  886.             *NextBuffer -> SerialIndex++ = c;
  887.         }
  888.     }
  889. }
  890.  
  891.     /* com_purge(VOID):
  892.      *
  893.      *    Clear the read/write buffers.
  894.      */
  895.  
  896. VOID
  897. com_purge(VOID)
  898. {
  899.     if(ThisBuffer -> IsBusy)
  900.     {
  901.         if(!CheckIO(ThisBuffer -> SerialRequest))
  902.             AbortIO(ThisBuffer -> SerialRequest);
  903.  
  904.         WaitIO(ThisBuffer -> SerialRequest);
  905.     }
  906.  
  907.     ThisBuffer -> IsBusy        = FALSE;
  908.     ThisBuffer -> SerialIndex    = ThisBuffer -> SerialBuffer;
  909.  
  910.     NextBuffer -> IsBusy        = FALSE;
  911.     NextBuffer -> SerialIndex    = NextBuffer -> SerialBuffer;
  912.  
  913.     if(ReadBuffer -> IsBusy)
  914.     {
  915.         if(!CheckIO(ReadBuffer -> SerialRequest))
  916.             AbortIO(ReadBuffer -> SerialRequest);
  917.  
  918.         WaitIO(ReadBuffer -> SerialRequest);
  919.     }
  920.  
  921.     ReadBuffer -> IsBusy        = FALSE;
  922.     ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  923.     ReadBuffer -> SerialFilled    = 0;
  924.  
  925.     ThisBuffer -> SerialRequest -> IOSer . io_Command = CMD_CLEAR;
  926.     DoIO(ThisBuffer -> SerialRequest);
  927. }
  928.  
  929.     /* com_dump(VOID):
  930.      *
  931.      *    Wait for asynchronous write request to terminate.
  932.      */
  933.  
  934. VOID
  935. com_dump(VOID)
  936. {
  937.     com_flush();
  938. }
  939.  
  940.     /* com_getbyte(VOID):
  941.      *
  942.      *    Read a single byte from the serial line. If not available,
  943.      *    return EOF.
  944.      */
  945.  
  946. int
  947. com_getbyte(VOID)
  948. {
  949.     int Result;
  950.  
  951.     if(ReadBuffer -> SerialFilled <= 0)
  952.     {
  953.         if(ReadBuffer -> IsBusy)
  954.         {
  955.             if(!CheckIO(ReadBuffer -> SerialRequest))
  956.                 return(EOF);
  957.             else
  958.                 WaitIO(ReadBuffer -> SerialRequest);
  959.  
  960.             ReadBuffer -> IsBusy        = FALSE;
  961.             ReadBuffer -> SerialFilled    = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  962.             ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  963.  
  964.             ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  965.  
  966.             DoIO(ReadBuffer -> SerialRequest);
  967.  
  968.             if(ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  969.             {
  970.                 LONG Size = ReadBuffer -> SerialSize - ReadBuffer -> SerialFilled;
  971.  
  972.                 if(Size > 0)
  973.                 {
  974.                     if(Size > ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  975.                         Size = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  976.  
  977.                     ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  978.                     ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer + ReadBuffer -> SerialFilled;
  979.                     ReadBuffer -> SerialRequest -> IOSer . io_Length    = Size;
  980.  
  981.                     DoIO(ReadBuffer -> SerialRequest);
  982.  
  983.                     ReadBuffer -> SerialFilled += ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  984.                 }
  985.             }
  986.         }
  987.         else
  988.         {
  989.             ReadBuffer -> SerialRequest -> IOSer . io_Command = SDCMD_QUERY;
  990.  
  991.             DoIO(ReadBuffer -> SerialRequest);
  992.  
  993.             if(!ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  994.                 return(EOF);
  995.             else
  996.             {
  997.                 ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  998.                 ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer;
  999.                 ReadBuffer -> SerialRequest -> IOSer . io_Length    = MIN(ReadBuffer -> SerialRequest -> IOSer . io_Actual,ReadBuffer -> SerialSize);
  1000.  
  1001.                 DoIO(ReadBuffer -> SerialRequest);
  1002.  
  1003.                 if(!ReadBuffer -> SerialRequest -> IOSer . io_Actual)
  1004.                     return(EOF);
  1005.                 else
  1006.                 {
  1007.                     ReadBuffer -> SerialFilled    = ReadBuffer -> SerialRequest -> IOSer . io_Actual;
  1008.                     ReadBuffer -> SerialIndex    = ReadBuffer -> SerialBuffer;
  1009.                 }
  1010.             }
  1011.         }
  1012.     }
  1013.  
  1014.     Result = *ReadBuffer -> SerialIndex++;
  1015.  
  1016.     ReadBuffer -> SerialFilled--;
  1017.  
  1018.     if(ReadBuffer -> SerialFilled <= 0)
  1019.     {
  1020.         ReadBuffer -> IsBusy                    = TRUE;
  1021.         ReadBuffer -> SerialIndex                = ReadBuffer -> SerialBuffer;
  1022.  
  1023.         ReadBuffer -> SerialRequest -> IOSer . io_Command    = CMD_READ;
  1024.         ReadBuffer -> SerialRequest -> IOSer . io_Data        = ReadBuffer -> SerialBuffer;
  1025.         ReadBuffer -> SerialRequest -> IOSer . io_Length    = 1;
  1026.  
  1027.         ClrSignal(SIG_SERREAD);
  1028.         SendIO(ReadBuffer -> SerialRequest);
  1029.     }
  1030.  
  1031.     return(Result);
  1032. }
  1033.  
  1034.     /* setstamp(STRPTR Name,LONG Time):
  1035.      *
  1036.      *    Set time/date of a file.
  1037.      */
  1038.  
  1039. VOID
  1040. setstamp(char *Name,long Time)
  1041. {
  1042.         struct tm *t;
  1043.     struct ClockData ClockData;
  1044.     ULONG Seconds;
  1045.     struct DateStamp Date;
  1046.  
  1047.         t = localtime(&Time);
  1048.  
  1049.     ClockData . sec        = t -> tm_sec;
  1050.     ClockData . min        = t -> tm_min;
  1051.     ClockData . hour    = t -> tm_hour;
  1052.     ClockData . mday    = t -> tm_mday;
  1053.     ClockData . month    = t -> tm_mon;
  1054.     ClockData . year    = t -> tm_year + 1900;
  1055.  
  1056.     Seconds = Date2Amiga(&ClockData);
  1057.  
  1058.     Date . ds_Days        = Seconds / (24 * 60 * 60);
  1059.     Date . ds_Minute    = (Seconds % (24 * 60 * 60)) / 60;
  1060.     Date . ds_Tick        = (Seconds % 60) * TICKS_PER_SECOND;
  1061.  
  1062.     SetFileDate(Name,&Date);
  1063. }
  1064.  
  1065.     /* freespace(STRPTR DrivePath):
  1066.      *
  1067.      *    Get free disk space for specified drive.
  1068.      */
  1069.  
  1070. long
  1071. freespace(char *DrivePath)
  1072. {
  1073.     struct DevProc    *DevProc = GetDeviceProc(DrivePath,NULL);
  1074.     struct DosList    *DosList;
  1075.     BOOL         GoodDevice = FALSE;
  1076.     LONG         Size = (LONG)((ULONG)~0 >> 2);
  1077.  
  1078.     if(DosList = LockDosList(LDF_DEVICES | LDF_READ))
  1079.     {
  1080.         while(DosList = NextDosEntry(DosList,LDF_DEVICES))
  1081.         {
  1082.             if(DosList -> dol_Task == DevProc -> dvp_Port)
  1083.             {
  1084.                 struct FileSysStartupMsg *FSSM = (struct FileSysStartupMsg *)BADDR(DosList -> dol_misc . dol_handler . dol_Startup);
  1085.  
  1086.                 if(TypeOfMem(FSSM))
  1087.                 {
  1088.                     struct DosEnvec *DosEnvec = (struct DosEnvec *)BADDR(FSSM -> fssm_Environ);
  1089.                     STRPTR Name = (STRPTR)BADDR(FSSM -> fssm_Device);
  1090.  
  1091.                     if(TypeOfMem(DosEnvec) && TypeOfMem(Name))
  1092.                     {
  1093.                         if(Name[0] > 0 && !Name[(WORD)Name[0] + 1])
  1094.                         {
  1095.                             struct IOStdReq __aligned IORequest;
  1096.  
  1097.                             if(!OpenDevice(Name + 1,FSSM -> fssm_Unit,&IORequest,FSSM -> fssm_Unit))
  1098.                             {
  1099.                                 CloseDevice(&IORequest);
  1100.  
  1101.                                 if(DosEnvec -> de_TableSize > 0 && DosEnvec -> de_LowCyl <= DosEnvec -> de_HighCyl)
  1102.                                     GoodDevice = TRUE;
  1103.                             }
  1104.                         }
  1105.                     }
  1106.                 }
  1107.             }
  1108.         }
  1109.  
  1110.         UnLockDosList(LDF_DEVICES | LDF_READ);
  1111.     }
  1112.  
  1113.     FreeDeviceProc(DevProc);
  1114.  
  1115.     if(GoodDevice)
  1116.     {
  1117.         struct InfoData *InfoData;
  1118.  
  1119.         if(InfoData = (struct InfoData *)AllocVec(sizeof(struct InfoData),MEMF_ANY | MEMF_PUBLIC))
  1120.         {
  1121.             UBYTE NewName[256],*Index;
  1122.             BPTR FileLock;
  1123.  
  1124.             memcpy(NewName,DrivePath,255);
  1125.  
  1126.             NewName[255] = 0;
  1127.  
  1128.             Index = PathPart(NewName);
  1129.  
  1130.             *Index = 0;
  1131.  
  1132.             FileLock = Lock(NewName,ACCESS_READ);
  1133.  
  1134.             if(FileLock)
  1135.             {
  1136.                 if(Info(FileLock,InfoData))
  1137.                     Size = InfoData -> id_BytesPerBlock * (InfoData -> id_NumBlocks - InfoData -> id_NumBlocksUsed);
  1138.  
  1139.                 UnLock(FileLock);
  1140.             }
  1141.  
  1142.             FreeVec(InfoData);
  1143.         }
  1144.     }
  1145.  
  1146.     return(Size);
  1147. }
  1148.  
  1149.     /* ffirst(char *FileSpec):
  1150.      *
  1151.      *    Return name of first file matching the given specs.
  1152.      */
  1153.  
  1154. char *
  1155. ffirst(char *filespec)
  1156. {
  1157.     AnchorUsed = TRUE;
  1158.  
  1159.     if(MatchFirst(filespec,Anchor))
  1160.         return(NULL);
  1161.     else
  1162.         return((char *)Anchor -> ap_Buf);
  1163. }
  1164.  
  1165.     /* fnext(VOID):
  1166.      *
  1167.      *    Return name of next file matching the given specs.
  1168.      */
  1169.  
  1170. char *
  1171. fnext(VOID)
  1172. {
  1173.     AnchorUsed = TRUE;
  1174.  
  1175.     if(MatchNext(Anchor))
  1176.         return(NULL);
  1177.     else
  1178.         return((char *)Anchor -> ap_Buf);
  1179. }
  1180.